package com.jweb.framework.mvc;

import java.io.IOException;

import javax.servlet.ServletConfig;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.ServletRegistration;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.jweb.framework.AppConstant;
import com.jweb.framework.core.CoreLoader;
import com.jweb.framework.mvc.action.Handler;
import com.jweb.framework.mvc.handler.HandlerExceptionResolver;
import com.jweb.framework.mvc.handler.HandlerInvoker;
import com.jweb.framework.mvc.handler.HandlerMapping;
import com.jweb.framework.util.FormatUtil;
import com.jweb.framework.util.WebUtil;

@WebServlet(urlPatterns = "/", loadOnStartup = 0)
public class DispatcherServlet extends HttpServlet {

	private final Logger logger = LoggerFactory.getLogger(getClass());
	private static final long serialVersionUID = -4125107833350340877L;

	private HandlerMapping handlerMapping = new HandlerMapping();
	private HandlerInvoker handlerInvoker = new HandlerInvoker();
	private HandlerExceptionResolver handlerExceptionResolver = new HandlerExceptionResolver();

	@Override
	public void init(ServletConfig config) throws ServletException {
		ServletContext context = config.getServletContext();
		CoreLoader.init();
		addIgnoreMapping(context);
		addJSPMapping(context);
	}

	@Override
	protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		// 获取当前请求相关数据
		String currentRequestMethod = request.getMethod();
		String currentRequestPath = WebUtil.getRequestPath(request);
		logger.debug("[Action] {}:{}", currentRequestMethod, currentRequestPath);
		// 将“/”请求重定向到首页
		if (currentRequestPath.equals("/")) {
			WebUtil.redirectRequest(AppConstant.CONFIG.AppHomePage.getValue(), request, response);
			return;
		}
		// 去掉当前请求路径末尾的“/”
		if (currentRequestPath.endsWith("/")) {
			currentRequestPath = currentRequestPath.substring(0, currentRequestPath.length() - 1);
		}
		// 获取 Handler
		Handler handler = handlerMapping.getHandler(currentRequestMethod, currentRequestPath);
		// 若未找到 Action，则跳转到 404 页面
		if (handler == null) {
			WebUtil.sendError(HttpServletResponse.SC_NOT_FOUND, "", response);
			return;
		}
		// 初始化 DataContext
		DataContext.init(request, response);
		try {
			// 调用 Handler
			handlerInvoker.invokeHandler(request, response, handler);
		} catch (Exception e) {
			e.printStackTrace();
			// 处理 Action 异常
			handlerExceptionResolver.resolveHandlerException(request, response, e);
		} finally {
			// 销毁 DataContext
			DataContext.destroy();
		}
	}

	// ==============================================================
	public void addIgnoreMapping(ServletContext context) {
		ServletRegistration defaultServlet = context.getServletRegistration("default");
		defaultServlet.addMapping("/favicon.ico");
		String IGNORE_PATH = FormatUtil.toStringTrim(AppConstant.CONFIG.AppIgnorePath.getValue());
		if (IGNORE_PATH.length() > 0) {
			defaultServlet.addMapping(IGNORE_PATH + "*");
		}
	}

	public void addJSPMapping(ServletContext context) {
		ServletRegistration jspServlet = context.getServletRegistration("jsp");
		jspServlet.addMapping(AppConstant.CONFIG.AppHomePage.getValue());
		String jspPath = FormatUtil.toStringTrim(AppConstant.CONFIG.AppViewPath.getValue());
		if (jspPath.length() > 0) {
			jspServlet.addMapping(jspPath + "*");
		}
	}
}
